#include <linux/init.h>
#include <linux/hrtimer.h>
#include <linux/printk.h>

#include <stdlib.h>

static struct hrtimer timer;
static struct hrtimer htabs;
static ktime_t htabs_tstart;

static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer)
{
    printk("hrtimer_callback\n");
    return HRTIMER_NORESTART;
}

static enum hrtimer_restart hrtimer_cb_abs(struct hrtimer *timer)
{
    int val = ktime_get() - htabs_tstart;

    printk("iv %d\n", val);

    return HRTIMER_NORESTART;
}

static int hrtimer(int argc, char **argv)
{
    int id = 0;

    if (argc == 2)
        id = atoi(argv[1]);

    switch (id)
    {
    case 0:
    {
        hrtimer_setup(&timer, hrtimer_callback, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);

        hrtimer_start(&timer, 1000000, HRTIMER_MODE_REL_HARD);
    }
    break;
    case 1:
    {
        hrtimer_setup(&htabs, hrtimer_cb_abs, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
    }
    break;
    case 2:
    {
        htabs_tstart = ktime_get();

        hrtimer_set_expires(&htabs, htabs_tstart);
        hrtimer_forward(&htabs, htabs_tstart, 1000000000);
        hrtimer_start_expires(&htabs, HRTIMER_MODE_ABS_PINNED_HARD);
    }
    break;
    }

    return 0;
}

#include <msh/export.h>
MSH_CMD_EXPORT(hrtimer, test hrtimer);
